<template>
  <el-container style="height: 100%">
    <el-header :height="headerHeight">
      <el-card :body-style="bodyStyle">
        <template #header>
          <div class="header">
            <div class="title">
              <slot name="title"></slot>
            </div>
            <div class="button">
              <el-button-group>
                <el-button
                  @click="queryClick"
                  type="primary"
                  :disabled="loading"
                  plain
                  :size="props.size"
                  >{{ t('components.DataTable.query') }}</el-button
                >
                <el-button
                  @click="clearForm"
                  type="info"
                  plain
                  :disabled="loading"
                  :size="props.size"
                  >{{ t('components.DataTable.clear') }}</el-button
                >
                <el-button v-if="props.export" type="success" plain :size="props.size">{{
                  t('components.DataTable.export')
                }}</el-button>
              </el-button-group>
              <el-button-group style="margin-left: 10px">
                <slot name="button" :rows="selectData" :row="selectRow" :size="selectSize"> </slot>
              </el-button-group>
            </div>
            <div style="clear: both"></div>
          </div>
        </template>
        <el-scrollbar :height="scrollHeight" v-if="slotQuery">
          <el-form inline :model="queryData">
            <slot name="query" :data="queryData"></slot>
            <div style="clear: both"></div>
          </el-form>
        </el-scrollbar>
      </el-card>
    </el-header>
    <el-main>
      <el-card>
        <el-table
          ref="table"
          :style="tableHeight"
          :data="datas"
          border
          :show-overflow-tooltip="true"
          :highlight-current-row="true"
          v-loading="loading"
          :element-loading-text="t('common.loadMessage')"
          @row-dblclick="dbClick"
          @row-click="rowClick"
          @selection-change="selectChange"
          @current-change="currentChange"
        >
          <el-table-column v-if="props.multiple" type="selection" width="35" />
          <slot name="column"></slot>
        </el-table>
      </el-card>
    </el-main>
    <el-footer height="32px">
      <el-pagination
        v-model:current-page="currentPage"
        v-model:page-size="pageSize"
        :page-sizes="[20, 50, 100, 200, 300, 400]"
        layout="total, prev, pager, next, jumper, sizes"
        :total="total"
      />
    </el-footer>
  </el-container>
</template>
<script setup lang="ts">
import {
  ref,
  defineProps,
  computed,
  defineModel,
  reactive,
  useSlots,
  watch,
  CSSProperties,
  toRaw
} from 'vue'
import { QueryFormType, QueryType, TableModel } from './types'
import { useI18n } from '@/hooks/web/useI18n'
import { ElTable } from 'element-plus'
import { Base64 } from 'js-base64'
import request from '@/axios'
import { debounce } from 'lodash-es'

const { t } = useI18n()

const loading = ref<boolean>(false)

const queryFormData = defineModel<QueryFormType>()
const slotQuery = !!useSlots().query

//定义返回事件

const emit = defineEmits(['dbClick', 'rowClick'])

//获取配置参数
const props = withDefaults(defineProps<TableModel>(), {
  height: 50,
  pageSize: 20,
  currentPage: 1,
  isLayout: true,
  select: false,
  multiple: false,
  size: '',
  offsetHeight: 0,
  changeLoad: false,
  fristLoad: true
})

//判断是否绑定了v-model
if (!queryFormData.value) {
  queryFormData.value = {}
}

//构建表单设置
const queryData = reactive(queryFormData.value)

//表单对象
const table = ref<InstanceType<typeof ElTable>>()

//选择的数据
const selectData = ref<any[]>([])

//选择一条
const selectRow = ref<any>(null)

//选择的条数
const selectSize = ref<number>(0)
//总条数
const total = ref(0)
//获取首次查询的页码
const currentPage = ref(props.currentPage)
//获取查询的条数
const pageSize = ref(props.pageSize)

const selectChange = () => {
  if (props.multiple) {
    if (selectRow.value != null) {
      table.value!.toggleRowSelection(selectData, false)
    }

    selectData.value = table.value!.getSelectionRows()
    selectSize.value = selectData.value.length

    if (selectData.value.length == 1) {
      selectRow.value = selectData.value[0]
    } else {
      selectRow.value = null
    }
  }
}

const currentChange = (row) => {
  if (!props.multiple) {
    selectRow.value = row
    selectSize.value = 1
    selectData.value = [row]
  }
}

const rowClick = async (row) => {
  emit('rowClick', toRaw(row))
  if (props.multiple) {
    table.value!.toggleRowSelection(row)
  }
}

//可以清空的参数
const clearParams = {}

//参数查询方式
const formQueryParams = {}

if (queryFormData.value) {
  for (const key in queryFormData.value) {
    const item = queryFormData.value[key]
    //默认是相匹配
    formQueryParams[key] = item.queryType ? item.queryType : QueryType.EQ
    if (item.clear === true || item.clear == undefined) {
      clearParams[key] = true
    }
  }
}

const scrollHeight = computed(() => {
  return props.height + 'px'
})

const headerHeight = computed(() => {
  if (slotQuery) {
    const h = props.height + 100
    return h + 'px'
  } else {
    return '60px'
  }
})

const bodyStyle = computed(() => {
  if (slotQuery) {
    return ''
  } else {
    return 'display:none'
  }
})
//calc(100vh - 410px)
const tableHeight = computed((): CSSProperties => {
  const offsetHeight = props.offsetHeight
  if (props.tableHeight) {
    return { height: props.tableHeight }
  } else if (props.isLayout) {
    if (slotQuery) {
      const height = props.height + offsetHeight + 388
      return { height: 'calc(100vh - ' + height + 'px)' }
    } else {
      const height = 348 + offsetHeight
      return { height: 'calc(100vh - ' + height + 'px)' }
    }
  } else {
    return {}
  }
})

const clearForm = () => {
  for (let key in clearParams) {
    queryData[key].value = ''
  }
  if (currentPage.value == 1) {
    load()
  } else {
    currentPage.value = 1
  }
  //重新加载
  //load(1)
}

const datas = ref([])

//查询数据方法
const load = () => {
  if (!loading.value) {
    loading.value = true
    query()
  } else {
    //在未返回值之前，不能允许重复提交查询。
  }
}

const query = async () => {
  const params = {
    limit: {
      pageSize: pageSize.value,
      currentPage: currentPage.value
    }
  }
  for (const key in queryData) {
    const value = queryData[key].value
    if (value != undefined && value != '') {
      const suffix = !(formQueryParams[key].suffix === false)
      switch (formQueryParams[key]) {
        case QueryType.LIKE:
          if (suffix) {
            params[key + '-lk'] = '%' + value + '%'
          } else {
            params[key] = '%' + value + '%'
          }
          break
        case QueryType.LIKE_L:
          if (suffix) {
            params[key + '-lk'] = '%' + value
          } else {
            params[key] = '%' + value
          }
          break
        case QueryType.LIKE_R:
          if (suffix) {
            params[key + '-lk'] = value + '%'
          } else {
            params[key] = value + '%'
          }
          break
        case QueryType.EQ:
          params[key] = value
          break
        case QueryType.NOT_IN:
          if (suffix) {
            params[key + '-nin'] = value
          } else {
            params[key] = value
          }
          break
        case QueryType.IN:
          if (suffix) {
            params[key + '-in'] = value
          } else {
            params[key] = value
          }
          break
        case QueryType.LE:
          if (suffix) {
            params[key + '-le'] = value
          } else {
            params[key] = value
          }
          break
        case QueryType.GE:
          if (suffix) {
            params[key + '-ge'] = value
          } else {
            params[key] = value
          }
          break
        case QueryType.LT:
          if (suffix) {
            params[key + '-lt'] = value
          } else {
            params[key] = value
          }
          break
        case QueryType.GT:
          if (suffix) {
            params[key + '-gt'] = value
          } else {
            params[key] = value
          }
          break
        case QueryType.NE:
          if (suffix) {
            params[key + '-ne'] = value
          } else {
            params[key] = value
          }
          break
        default:
          params[key] = value
          break
      }
    }
  }

  const option: AxiosConfig = {
    url: props.loadUrl,
    data: params
  }

  if (props.convert) {
    option.convert = props.convert
  }

  if (props.export) {
    const bpmsExportConfig = Base64.encode(JSON.stringify(props.export))
    option.headers = {
      'Bmps-Export-Config': bpmsExportConfig
    }
  }

  const rs = await request.post(option, {
    close: () => {
      loading.value = false
    }
  })
  if (rs.success) {
    datas.value = rs.data
    total.value = rs.total
  }
}

if (props.changeLoad) {
  watch(
    queryData,
    debounce(() => {
      load()
    }, 500)
  )
}

const queryClick = () => {
  if (currentPage.value == 1) {
    load()
  } else {
    currentPage.value = 1
  }
}

//监听页码变更
watch(
  currentPage,
  debounce(() => {
    load()
  }, 500)
)

//行的双击事件
const dbClick = (row: any, column: any) => {
  emit('dbClick', row, column)
}

//首次加载
if (props.fristLoad) {
  load()
}

const getRow = () => {
  return toRaw(selectRow.value)
}

const getRows = () => {
  return toRaw(selectData.value)
}
//对外暴露load方法
defineExpose({
  load,
  getRow,
  getRows
})
</script>

<style scoped>
.header {
  width: 100%;
}
.header .title {
  float: left;
}
.query-form {
  width: 100%;
}
.header .button {
  float: right;
}

:deep(.el-table__body tr.current-row > td) {
  background-color: #2291ff;
  color: #fff;
}
:deep(.el-table__body tr.el-table__row:hover > td) {
  background-color: #409eff;
  color: #fff;
}
</style>
